// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#include <melon/dynamic.h>
#include <sstream>
#include <string>
#include <pollux/common/base/bit_util.h>
#include <pollux/common/base/exceptions.h>
#include <pollux/common/strings/string_view.h>

#pragma once

namespace kumo::pollux {
    using int128_t = __int128_t;
    using uint128_t = __uint128_t;

    class HugeInt {
    public:
        static constexpr MELON_ALWAYS_INLINE int128_t
        build(uint64_t hi, uint64_t lo) {
            // GCC does not allow left shift negative value.
            return (static_cast<__uint128_t>(hi) << 64) | lo;
        }

        static constexpr MELON_ALWAYS_INLINE uint64_t lower(int128_t value) {
            return static_cast<uint64_t>(value);
        }

        static constexpr MELON_ALWAYS_INLINE uint64_t upper(int128_t value) {
            return static_cast<uint64_t>(value >> 64);
        }

        static MELON_ALWAYS_INLINE int128_t deserialize(const char *serializedData) {
            int128_t value;
            memcpy(&value, serializedData, sizeof(int128_t));
            return value;
        }

        static MELON_ALWAYS_INLINE void serialize(
            const int128_t &value,
            char *serializedData) {
            memcpy(serializedData, &value, sizeof(int128_t));
        }

        static int128_t parse(const std::string &str);
    };
} // namespace kumo::pollux

namespace std {
    string to_string(__int128_t x);
} // namespace std
